using System;
using System.Collections.Generic;
using System.Configuration;

namespace Beetle.Clients;

public class AsnyPool<T> where T : Package
{
	private class NodeIndex
	{
		public int a;
	}

	private EventPacketRecievMessage a;

	private EventChannelError b;

	private Action<IChannel> c;

	private List<AsynNode<T>> d = new List<AsynNode<T>>();

	[ThreadStatic]
	private static NodeIndex e;

	[ThreadStatic]
	private static int f = 0;

	public IList<AsynNode<T>> Nodes => d;

	public AsnyPool(EventPacketRecievMessage receive, EventChannelError error, Action<IChannel> channelCreated)
	{
		a = receive;
		b = error;
		c = channelCreated;
	}

	public AsnyPool(string section, EventPacketRecievMessage receive, EventChannelError error, Action<IChannel> channelCreated)
	{
		a = receive;
		b = error;
		PoolSection poolSection = (PoolSection)ConfigurationManager.GetSection(section);
		if (poolSection == null)
		{
			throw NetTcpException.ClientPoolSectionNotFound(section);
		}
		if (section == null)
		{
			return;
		}
		foreach (ServerNode server in poolSection.Servers)
		{
			AddNode(server.Name, server.Host, server.Port, server.MaxConnections, server.DetectTime, server.Group);
		}
	}

	public void Connect()
	{
		List<string> list = new List<string>();
		foreach (AsynNode<T> node in Nodes)
		{
			list.Clear();
			foreach (AsynNode<T> node2 in Nodes)
			{
				if (node != node2 && node.GroupName == node2.GroupName)
				{
					list.Add(node2.GroupName);
				}
			}
			node.GroupNodes = list.ToArray();
			node.Connect();
		}
	}

	public void AddNode(string name, string host, int port, int maxconnections)
	{
		AddNode(name, host, port, maxconnections, 30, null);
	}

	public void AddNode(string name, string host, int port, int maxconnections, int detectTime, string groupName)
	{
		AsynNode<T> asynNode = new AsynNode<T>(host, port, maxconnections, a, b, c);
		asynNode.Name = name;
		asynNode.DetectTime = detectTime;
		asynNode.GroupName = groupName;
		Nodes.Add(asynNode);
	}

	public bool Send(object message)
	{
		AsynNode<T> node = GetNode();
		if (node == null || !node.Available)
		{
			throw NetTcpException.ConnectionIsNotAvailable();
		}
		return node.Send(message);
	}

	public bool Send(object message, params string[] nodes)
	{
		AsynNode<T> node = GetNode(nodes);
		if (node == null || !node.Available)
		{
			throw NetTcpException.ConnectionIsNotAvailable();
		}
		return node.Send(message);
	}

	public virtual AsynNode<T> GetNode(params string[] nodes)
	{
		AsynNode<T> asynNode = null;
		int num = 0;
		while (num < nodes.Length)
		{
			f++;
			if (f >= nodes.Length)
			{
				f = 0;
			}
			for (int i = 0; i < Nodes.Count; i++)
			{
				asynNode = Nodes[i];
				if (nodes[f] == asynNode.Name && asynNode.Available)
				{
					return asynNode;
				}
			}
		}
		return null;
	}

	public virtual AsynNode<T> GetNode()
	{
		if (e == null)
		{
			e = new NodeIndex();
		}
		if (d.Count == 0)
		{
			return null;
		}
		int i = 0;
		AsynNode<T> asynNode = null;
		for (; i <= d.Count; i++)
		{
			e.a++;
			if (e.a >= d.Count)
			{
				e.a = 0;
			}
			asynNode = d[e.a];
			if (asynNode.Available)
			{
				return asynNode;
			}
		}
		return null;
	}
}
